package cn.tedu.charging.cost.dao.repository.impl;

import cn.tedu.charging.cost.dao.mapper.CostRuleMapper;
import cn.tedu.charging.cost.dao.repository.CostRuleRepository;
import cn.tedu.charging.cost.pojo.po.ChargingCostRulePO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Slf4j
public class CostRuleRepositoryImpl implements CostRuleRepository {
    @Autowired
    private CostRuleMapper costRuleMapper;
    @Autowired
    private RedisTemplate<String,ChargingCostRulePO> redisTemplate;
    @Override
    public ChargingCostRulePO getCostRule(Integer stationId, Integer hour) {
        /**
         * name   start  end  power_fee gun_type station_id
         * 尖上午   08     12     1.50   快      5     #场站id是5,时间段[08,12) 按照1.5元/度
         * 尖下午   14     18     1.50   快      5     #场站id是5,时间段[14,18) 按照1.5元/度
         * 全天峰   18     24     1.40   快      5     #场站id是5,时间段[18,24) 按照1.4元/度
         * 全天平   12     14     1.30   快      5     #场站id是5,时间段[12,14) 按照1.3元/度
         * 全天谷   00     08     1.00   快      5     #场站id是5,时间段[00,08) 按照1.0元/度
         */
        //方案3: 先读取redis 命中则直接使用 未命中再读数据库
        String stationRulesKey="charging:station:rules:"+stationId;
        //拿到操作list数据的redis对象
        ListOperations<String, ChargingCostRulePO> listOps = redisTemplate.opsForList();
        //1.读取缓存 lrange key 0 -1 把一个list所有元素都读取
        List<ChargingCostRulePO> costRulePOs = listOps.range(stationRulesKey, 0, -1);
        //判断命中结果
        if(costRulePOs==null||costRulePOs.size()==0){
            log.debug("缓存未命中,开始查询数据库,stationId:{}",stationId);
            //2.读取数据库数据
            QueryWrapper<ChargingCostRulePO> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("station_id",stationId);
            costRulePOs=costRuleMapper.selectList(queryWrapper);
            //3.回填到缓存 lpush key mem1 mem2....
            listOps.leftPushAll(stationRulesKey,costRulePOs);
        }else{
            log.debug("缓存命中,直接筛选,stationId:{}",stationId);
        }
        //4.从当前的规则列表中,利用时间小时数筛选最终的结果
        return costRulePOs.stream().filter(po->po.getStartTime()<=hour&&po.getEndTime()>hour)
                .findFirst().orElse( null);
    }
    //方案2: 不直接在数据库拼所有where条件
    //1.利用stationId 查询这个场站关联绑定的所有规则
    /*QueryWrapper<ChargingCostRulePO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("station_id",stationId);
    List<ChargingCostRulePO> costRulePOs=costRuleMapper.selectList(queryWrapper);
    //2.遍历所有的po,筛选出满足时间小时数条件的规则 stream().filter()
        return costRulePOs.stream().filter(po->po.getStartTime()<=hour&&po.getEndTime()>hour)
            .findFirst().orElse( null);*/
    //方案1: 利用条件直接查询一个计价规则
    //select * from cost_rule where station_id=? and start_time<=hour and end_time>hour
    /*QueryWrapper<ChargingCostRulePO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("station_id",stationId);
        queryWrapper.le("start_time",hour);
        queryWrapper.gt("end_time",hour);
        return costRuleMapper.selectOne(queryWrapper);*/
}
